package com.wulis.seckill.aop;

import com.wulis.seckill.common.wrapper.ResponseDataUtil;
import lombok.AllArgsConstructor;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.redisson.Redisson;
import org.redisson.api.RRateLimiter;
import org.redisson.api.RateIntervalUnit;
import org.redisson.api.RateType;
import org.springframework.stereotype.Component;
import org.aspectj.lang.reflect.MethodSignature;

import java.lang.reflect.Method;

@Aspect
@Component
@AllArgsConstructor
public class RedisRLimiterAspect {

    private final Redisson redisson;

    /**
     * aop切入点
     */
    @Pointcut("@annotation(com.wulis.seckill.aop.RedisLimiter)")
    public void pointcut() {
    }

    /**
     * AOP 切入代码
     *
     * @param pjp
     * @return
     * @throws Throwable
     */
    @Around("pointcut()")
    public Object interceptor(ProceedingJoinPoint pjp) throws Throwable {
        MethodSignature signature = (MethodSignature) pjp.getSignature();
        Method method = signature.getMethod();
        RedisLimiter limit = method.getAnnotation(RedisLimiter.class);
        //获取redis限流器
        RRateLimiter rateLimiter = redisson.getRateLimiter(limit.name());
        // 初始化
        // 最大流速 = 每limit.period()秒钟产生limit.count()个令牌
        rateLimiter.trySetRate(RateType.OVERALL, limit.count(), limit.period(), RateIntervalUnit.SECONDS);
        if (!rateLimiter.tryAcquire()) {
            return ResponseDataUtil.buildError("获取令牌失败");
        }
        return pjp.proceed();
    }

}
